package com.PictureSite.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.PictureSite.DatabaseAccess.PictureSiteCreatePostDAO;
import com.PictureSite.Validator.PictureSiteCreatePostValidator;
import com.PictureSite.model.PictureSitePostModel;
import com.PictureSite.model.UserPost;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileWriteChannel;

public class PictureSiteCreatePostController extends PictureSiteController {

	private final FileService fileService;
	
	final private static String postView ="post.html";
	
	private PictureSiteCreatePostValidator validator = new PictureSiteCreatePostValidator();

	public PictureSiteCreatePostController(final FileService fileService) {
		this.fileService = fileService;
	}

	private static final Logger log = Logger.getLogger(FileUpload.class
			.getName());

	private PictureSiteCreatePostDAO dataStore = new PictureSiteCreatePostDAO();

	public void submitPost(HttpServletRequest req, HttpServletResponse resp,
			PictureSitePostModel model) throws Exception {
		UserPost newPost = new UserPost();
		try {
			ServletFileUpload upload = new ServletFileUpload();
			FileItemIterator iterator = upload.getItemIterator(req);

			while (iterator.hasNext()) { 
				FileItemStream item = iterator.next();

				if (item.isFormField()) { 
					streamTextContent(item,newPost);
				} else {				
					// Declare mimetype for the image
					String mimeType = "image/png";
					// save data to Google App Engine Blobstore
					AppEngineFile file = fileService.createNewBlobFile(mimeType);
					streamImageContent(item, file);
					// Now read from the file using the Blobstore API
					BlobKey blobKey = fileService.getBlobKey(file);
					newPost.setBlobId(blobKey.getKeyString());
				}
			}
		} catch (Exception e) {
			log.info("Error when creating post: "+e);
		}

		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"yyyy-MMM-dd HH:mm:ss");
		dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
		newPost.setDatePosted(dateFormat.format(new Date()));
		if(!validator.validatePost(newPost)) {
			resp.sendError(1,"Field is null");
			bindModel(model, postView, resp);
		} else {
			dataStore.storePost(newPost); 
		}
	}
	
	private void streamTextContent(FileItemStream in, UserPost newPost) {
		
		// data comes from here
		InputStream stream = null;
		
		try {
			stream = in.openStream();
            int len = 0;
			byte[] buffer = new byte[8192];

			ByteArrayOutputStream file = new ByteArrayOutputStream();
			
            while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
                file.write(buffer, 0, len);
              }

            if (in.getFieldName().equals("username")) {
            	newPost.setUserName(file.toString());
            } else if (in.getFieldName().equals("title")) {
            	newPost.setTitle(file.toString());
            }
            
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		} finally {
			try {
				if (stream != null) {
					stream.close();
				}
			} catch (IOException e) {
				// closing a stream failed - ignore...
			}
		}
	}


	private void streamImageContent(FileItemStream in, AppEngineFile out) {

		// data comes from here
		InputStream inStream = null;

		// data goes here
		OutputStream outStream = null;

		try {
			inStream = in.openStream();
			FileWriteChannel fileChannel = fileService.openWriteChannel(out,
					true);
			outStream = Channels.newOutputStream(fileChannel);

			byte[] buffer = new byte[1024];

			// priming read
			int bytesRead = inStream.read(buffer);
			while (bytesRead > 0) {

				// write the buffer out
				outStream.write(buffer, 0, bytesRead);

				// next read!
				bytesRead = inStream.read(buffer);
			}
			fileChannel.closeFinally();

		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		} finally {
			try {
				if (inStream != null) {
					inStream.close();
				}
				if (outStream != null) {
					outStream.close();
				}
			} catch (IOException e) {
				// closing a stream failed - ignore...
			}
		}

	}

}
